#include "SocketKqueueDemo.h"
#include <iostream>

using namespace std;

#ifdef __APPLE__
#include <sys/event.h>

SOCKET createKqueueService(int port)
{
    // 1. 创建 Socket
    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == -1)
    {
        cerr << "创建失败！！" << endl;
        return -1;
    }

    // 2. bind IP端口
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(port);
    int bindRet = ::bind(serverSocket, (sockaddr *)&serverAddr, sizeof(serverAddr));
    if (bindRet == -1)
    {
        cerr << "绑定端口失败！！！" << endl;
        compatCloseSocket(serverSocket);
        return -1;
    }

    // 3. listen
    int listenRet = listen(serverSocket, 1024);
    if (listenRet == -1)
    {
        cerr << "监听失败！！！" << endl;
        compatCloseSocket(serverSocket);
        return -1;
    }

    return serverSocket;
}

void simpleKqueueDemo()
{
    SOCKET serverSocket = createKqueueService(9999);
    // 类似 epoll_create
    int kq = kqueue();
    if(kq == -1)
    {
        cerr << "kqueue create 失败!!!" << endl;
        compatCloseSocket(serverSocket);
        return;
    }

    struct kevent events[100];

    // 设定 kevent 参数的宏，详细解释见后面的调用示例
    EV_SET(&events[0], ident, filter, flags, fflags, data, udata);

    // 组合了 epoll_ctl 及 epoll_wait 功能，changelist 与 nchanges 为修改列表，eventlist 与 nevents 为返回的事件列表
    int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); 

}

void threadKqueueDemo()
{

}

#endif

void socketKqueueDemo()
{
    // apple mac 系统没有 epoll 库，只有 linux 存在 epoll 库。但 mac 提供了类似 epoll 的替代库。



    cout << "案例八：IO多路转接（复用）之 kqueue 方案（apple 平台的 epoll 替代）" << endl;

#ifdef __APPLE__
    cout << "请选择演示哪一种实现：" << endl;
    cout << "1. kqueue 模型的单线程实现多路转接并发处理" << endl;
    cout << "2. kqueue 模型的基于线程池复用多路转接并发处理" << endl;

    char commond;
    cin >> commond;
    switch (tolower(commond))
    {
    case '1':
        simpleKqueueDemo();
        break;
    case '2':
        threadKqueueDemo();
        break;
    }
#else
    cout << "非 mac os 操作系统平台不支持 kqueue 模型！！可以查看 epoll 模型以及 IOCP 模型" << endl;
#endif
}